package com.website.shiro;

import com.website.shiro.filter.MyFormAuthenticationFilter;
import com.website.shiro.filter.PermissionFilter;
import lombok.Data;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.AbstractShiroWebFilterConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 * @author zhangshuw
 * <p>     2019/7/4
 */
@Configuration
public class ShiroConfiguration extends AbstractShiroWebFilterConfiguration {


    @Bean
    @ConfigurationProperties(prefix = "shiro")
    public ShiroProperties shiroProperties() {
        return new ShiroProperties();
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/login", "authc");
        chainDefinition.addPathDefinition("/online/index.html", "authc");
        chainDefinition.addPathDefinition("/admin/**", "authc,perm");
        chainDefinition.addPathDefinition("/logout", "logout");
        return chainDefinition;
    }

    @Bean
    @Override
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean filterFactoryBean = super.shiroFilterFactoryBean();
        filterFactoryBean.getFilters().put("authc", new MyFormAuthenticationFilter(shiroProperties().getValidAuthCode()));
        filterFactoryBean.getFilters().put("perm", new PermissionFilter());
        return filterFactoryBean;
    }

    /**
     * 需要定义为名称authorizer的bean，shiro加载SessionsSecurityManager bean会用到
     */
    @Bean("authorizer")
    public MyRealm myRealm(SessionManager sessionManager, RememberMeManager rememberMeManager) {
        if (sessionManager instanceof DefaultWebSessionManager && shiroProperties().getGlobalSessionTimeout() > 0) {
            ((DefaultWebSessionManager) sessionManager).setGlobalSessionTimeout(shiroProperties().getGlobalSessionTimeout());
        }
        if (rememberMeManager instanceof CookieRememberMeManager) {
            AbstractRememberMeManager m = (AbstractRememberMeManager) rememberMeManager;
            // m.setCipherKey(((AesCipherService)m.getCipherService()).generateNewKey(192).getEncoded());
            // AES 生成key的keyBitsize: must be equal to 128, 192 or 256，那么有效的AES key的byte数组长度是16 24 32位
            m.setCipherKey(Arrays.copyOf(shiroProperties().getCipherKey().getBytes(), 16));
        }
        return new MyRealm(new HashedCredentialsMatcher(Md5Hash.ALGORITHM_NAME));
    }

    @Data
    class ShiroProperties {

        private String cipherKey;

        private String validAuthCode = "true";

        private long globalSessionTimeout;

    }
}
